import java.util.ArrayList;



public class Cargador {
  //Declaramos las variables
  private ArrayList<String> imagenes;
  private String ruta;
  private int pos;
  private PImage imgAct;
  private ArrayList etiquetas;
  private String[] nombres;
  private XMLElement element;
  private XMLElement e;
  private int xmlPos;
  private int nEtiqueta=-1;
  private ArrayList<Etiqueta> deshacer;
  Etiqueta minima=null;
  Etiqueta etMin=null;
  private int xact=0;
  private int yact=0;

 //Constructor
  public Cargador(String ruta) {
    this.ruta = ruta;
    deshacer = new ArrayList();
  }
  
  public void reiniciarDeshacer(){
   deshacer.clear(); 
  }
 //Metodo que carga las imagenes del directorio especificado
  public void cargar(PApplet parent,Explorador explorador) {
    imagenes = new ArrayList();
    xmlPos=-1;
    boolean t = false;
    nombres = listarArchivos(ruta);
    println(nombres);
    //Recorremos las imagenes
    for(int i= 0; i< nombres.length;i++) {    
      String nombre = nombres[i];
      //Si encontramos el xml
      if(nombre.endsWith("xml")) {
        //Si el xml es el de definicion de etiquetas
        if(nombre.equals("tree.xml")){
        xmlPos=i;}
        //Si el xml es el de definicion de herramientas cargamos la configuracion
        else if(nombre.equals("tools.xml")){
         explorador.cargarConf(parent,this.ruta+"tools.xml"); 
         t=true;
        }  
      }
      
      //Cargamos la imagen
      else if(nombre.toLowerCase().endsWith("jpg")|| nombre.toLowerCase().endsWith("gif") || nombre.toLowerCase().endsWith("jpeg") || nombre.toLowerCase().endsWith("tga") || nombre.toLowerCase().endsWith("png")) {
        
        imagenes.add(ruta+nombres[i]);
        println("cargando "+nombre+" i: "+i);
      }
    }
    if(!t){
      // Si no hay fichero de configuracion de herramientas cargamos las herramientas por defecto
      explorador.cargarConf(parent,"tools.xml");
    }
    pos=0;
    //Seteamos la imagen inicial
     println(imagenes.toArray()[0]);
    imgAct =(PImage)loadImage((String)imagenes.toArray()[0]);
    
    etiquetas = new ArrayList();
    //Generamos el array de etiquetas para cada imagen
    for(int i = 0 ; i < imagenes.size();i++) {
      etiquetas.add(new ArrayList());
    }
    if(xmlPos!=-1) {
      //Si hay fichero de configuracion de etiquetas lo cargamos
      cargarXml(nombres[xmlPos],parent);
    }
    
  }
  //Funcion que carga un fichero xml de configuracion de etiquetas
  void cargarXml(String nombre,PApplet parent) {
    element = new XMLElement(parent,ruta+nombre);
    //Recorremos todos los tags de xml y miramos a que clase de etiqueta pertence para agregarlo como una nueva etiqueta.
    for (int i=0; i < element.getChildCount(); i++) {
      XMLElement imagen = element.getChild(i);
      String nImagen = imagen.getAttribute("src");
      for(int j = 0; j<nombres.length;j++) {
        if(nombres[j].equals(nImagen)) {
          for(int k = 0; k<imagen.getChildCount();k++) {
            XMLElement etiqueta = imagen.getChild(k);
            println(etiqueta);
            if(etiqueta.getName().equals("Square")) {
              String n = etiqueta.getStringAttribute("name");
              int x = Integer.valueOf(etiqueta.getStringAttribute("x")); 
              int y = Integer.valueOf(etiqueta.getStringAttribute("y"));
              float ancho = Float.valueOf(etiqueta.getStringAttribute("width"));
              float alto = Float.valueOf(etiqueta.getStringAttribute("height"));
              println(x+" "+y+" "+ancho+" "+alto);
              agregarEtiqueta(j,new Etiqueta(x,y,ancho,alto,n));
            }            
            if(etiqueta.getName().equals("Point")) {
              String n = etiqueta.getStringAttribute("name");
              int x = Integer.valueOf(etiqueta.getStringAttribute("x")); 
              int y = Integer.valueOf(etiqueta.getStringAttribute("y"));
              println(x+" "+y);
              agregarEtiqueta(j,new Etiqueta(x,y,n));
            }
            else if(etiqueta.getName().equals("Circle")) {
              String n = etiqueta.getStringAttribute("name");
              int x = Integer.valueOf(etiqueta.getStringAttribute("x")); 
              int y = Integer.valueOf(etiqueta.getStringAttribute("y"));
              float radio = Float.valueOf(etiqueta.getStringAttribute("radio"));
              agregarEtiqueta(j,new Etiqueta(x,y,radio,n));
            }
            else if(etiqueta.getName().equals("Poligon")){
              String n = etiqueta.getStringAttribute("name");
              ArrayList p = new ArrayList();
              for(int l = 0; l<etiqueta.getChildCount();l++){
               XMLElement pol = etiqueta.getChild(l);
                int[] punto = new int[2];
                 punto[0] = Integer.valueOf(pol.getStringAttribute("x")); 
                 punto[1] = Integer.valueOf(pol.getStringAttribute("y")); 
                 p.add(punto);
              }
              agregarEtiqueta(j,new Etiqueta(p,n,3));
            }
             else if(etiqueta.getName().equals("Pointsec")){
              String n = etiqueta.getStringAttribute("name");
              ArrayList p = new ArrayList();
              for(int l = 0; l<etiqueta.getChildCount();l++){
               XMLElement pol = etiqueta.getChild(l);
                int[] punto = new int[2];
                 punto[0] = Integer.valueOf(pol.getStringAttribute("x")); 
                 punto[1] = Integer.valueOf(pol.getStringAttribute("y")); 
                 p.add(punto);
              }
              agregarEtiqueta(j,new Etiqueta(p,n,5));
            }
          }
        }
      }
    }
  }
//Funcion que devuelve el numero de imagenes
public int getNImagenes(){
 return imagenes.size(); 
}
//Funcion que lista los archivos de un directorio
  String[] listarArchivos(String dir) {
    File file = new File(dir);
    if(file.isDirectory()) {
      String names[] = file.list();
      return names;
    }
    else {
      return null;
    }
  }
  //Funcion que devuelve la ultima etiqueta
  public Etiqueta getUltimaEtiqueta(int imagenActual){
    ArrayList et = (ArrayList)etiquetas.get(imagenActual);
    return (Etiqueta)et.get(nEtiqueta-1);  
  }
  //Funcion que añade una etiqueta al array 
  public void agregarEtiqueta(int nImagen,Etiqueta etiqueta) {    
    ArrayList e = (ArrayList)etiquetas.get(nImagen);    
    e.add(etiqueta);
    nEtiqueta++;
  }
  //Funcion que resetea la etiqueta mas cercana al puntero del raton
  public void resetMinima(){
    minima=null;
    etMin=null;
  }
  //Funcion que muestra por pantalla las etiquetas del array  
  public void dibujaretiquetas(int imagenActual,int offsetx,int offsety,boolean elim,float zoom,float zoomy,float dragX,float dragY) {
    nEtiqueta=0;   
    float distmin=1000;
    ArrayList e = (ArrayList)etiquetas.get(imagenActual);
    Iterator i = e.iterator();
    while(i.hasNext()) {
      Etiqueta et = (Etiqueta) i.next();
      et.display(offsetx,offsety,false,zoom,zoomy,dragX,dragY);
       if(xact!=mouseX && yact!=mouseY){
        //Calculamos la distancia entre el puntero y la etiqueta 
      if(distmin > et.getMinDist((int)offsetx,(int)offsety,zoom,zoomy,dragX,dragY)){
        float distmin2=et.getMinDist((int)offsetx,(int)offsety,zoom,zoomy,dragX,dragY);
        
         distmin = distmin2; 
        
        minima = et;
       
      }}
      nEtiqueta++;
    }
    if(xact!=mouseX && yact!=mouseY){
      xact=mouseX;
      yact=mouseY;
    }    
    if(elim & minima !=null){
     // println("entro");
     minima.display( offsetx,offsety,true,zoom,zoomy,dragX,dragY);
    }    
  }
  //Funcion que recupera la ultima etiqueta eliminada
  public void deshacer(int imagenActual){
    if(deshacer.size()!=0){
    ArrayList e = (ArrayList)etiquetas.get(imagenActual);
    Etiqueta et = deshacer.get(deshacer.size()-1);
    e.add(et);
    deshacer.remove(et);   
    }
  }
  //Funcion que mira si has presionado una etiqueta
  public boolean pressEtiquetas(int imagenActual,int offsetx,int offsety,float zoom,float dragX,float dragY) {
    ArrayList e = (ArrayList)etiquetas.get(imagenActual);
    Iterator i = e.iterator();
    while(i.hasNext()) {
      Etiqueta et = (Etiqueta) i.next();
      if(et.isPressed(offsetx,offsety,zoom,dragX,dragY)){
       e.remove(et);
       deshacer.add(et);
      return true ;
      }
    }
    return false;
  }
  //Geter de las imagenes
  public ArrayList<String> getImagenes() {
    return imagenes;
  }
  //Funcion que guarda las etiquetas en un xml
  public void guardarEtiquetas() {
    PrintWriter output = createWriter(ruta+"tree.xml");
    output.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
    Iterator i = etiquetas.iterator();
    int contador=0;
    output.println("<Images>");
    while(i.hasNext()) {
      ArrayList et = (ArrayList)i.next();
      Iterator i2 = et.iterator(); 
      output.println("\t <img src=\""+nombres[contador]+"\">");
      contador++; 
      while(i2.hasNext()) {
        Etiqueta etiqueta = (Etiqueta)i2.next();
        etiqueta.agregarTree(output);
      }
      output.println("\t</img>");
    }
    output.println("</Images>");
    output.flush();
    output.close();
  }
  //Funcion que retorna el numero de etiquetas
  public int getNumEtiquetas(){
    return nEtiqueta;
  }
  //Funcion que agrega las estiquetas al menu (outdated)
  public int agregarEtiquetasMenu(ListBox l,int imagenActual){
    int numEt=0;
    
    ArrayList et = (ArrayList)etiquetas.get(imagenActual);
    Iterator i = et.iterator();
    while(i.hasNext()){
      Etiqueta e = (Etiqueta) i.next();
      l.addItem(e.getNombre(),numEt);
      numEt++;
    }
    nEtiqueta = numEt-1;
    return numEt;
  }
  //Funcion que elimina una etiqueta
  public boolean borrarEtiqueta(int imagenActual){
    ArrayList a = (ArrayList) etiquetas.get(imagenActual);
    if(minima!=null){
     a.remove(minima);
     deshacer.add(minima);
    // println("minima: "+minima);
    minima=null; 
    return true;
    }
    return false;
  }
  //Funcion que setea la etiqueta mas proxima al raton
  void setEtMin(){
   etMin = minima; 
  // println(etMin);
  }
  //Geter de la etiqueta a modificar
  Etiqueta getEtiquetaModif(){   
    if(etMin!=null){
     // println(etMin);
      return etMin;}
      return null;
  }
}

